<!--
//
//  Copyright (c) 2011 Roy Six
//  http://code.google.com/p/urli/
//  License: LGPL v3.0
//
//  This file is part of urli.
//
//  urli is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  urli is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with urli.  If not, see <http://www.gnu.org/licenses/>.
//
-->

<!DOCTYPE HTML>

<html>

	<head>

		<title>urli Background</title>

		<!-- Javascript -->

		<script>

			// Prototype Constructors.
			// Note:  It is hard to implement multiple constructors in JavaScript
			// without some fancy tricks, so stick with just one.

			function URLIncrementer() {
			}

			// Prototype Variables And Functions.

			URLIncrementer.prototype = {

				// Variables (default values).

				enabled:		false,	// State relies on "clear" button input.
				tab:			null,	// Tab structure (tab id and tab url).
				selection:		"",		// Selection string that will be incremented.
				selectionStart:	-1,		// Start position of the selection relative to the URL.
				increment:		1,		// Amount to increment (or decrement).
				zeros:			true,	// State of "zeros" (whether to keep leading 0s).

				// Getters.

				getEnabled: function() {
					return this.enabled;
				},

				getTab: function() {
					return this.tab;
				},

				getSelection: function() {
					return this.selection;
				},

				getSelectionStart: function() {
					return this.selectionStart;
				},

				getIncrement: function() {
					return this.increment;
				},

				getZeros: function() {
					return this.zeros;
				},

				// Setters.

				setEnabled: function(enabled) {
					this.enabled = enabled;
				},

				setTab: function(tab) {
					this.tab = tab;
				},

				setSelection: function(selection) {
					this.selection = selection;
				},

				setSelectionStart: function(selectionStart) {
					this.selectionStart = selectionStart;
				},

				setIncrement: function(increment) {
					this.increment = increment;
				},

				setZeros: function(zeros) {
					this.zeros = zeros;
				},

				// Clear (resets values back to default).

				clear: function() {
					this.enabled = false;
					this.tab = null;
					this.selection = "";
					this.selectionStart = -1;
					this.increment = 1;
					this.zeros = true;
				}
			}
 
			// Global variables.

			var urli;			// A URLIncrementer object used to store information.
			var firstRunFlag;	// A boolean flag to go to options.html on first run.

			// Instantiate a new URLIncrementer object with default values.

			urli = new URLIncrementer();

			// Retrieves firstRunFlag's value from localStorage (if found).

			firstRunFlag = window.localStorage.getItem("firstRunFlag");

			// Runs only only once, if firstRunFlag does not exist.  Sets up
			// the default values.

			if (!firstRunFlag) {
				var optionsPageURL = chrome.extension.getURL("options.html");
				chrome.tabs.create({url: optionsPageURL});
				window.localStorage.setItem("firstRunFlag", "1");
				window.localStorage.setItem("keyEnabled", "1");
				window.localStorage.setItem("keyCodeIncrement", 38);
				window.localStorage.setItem("keyEventIncrement", " Ctrl");
				window.localStorage.setItem("keyCodeDecrement", 40);
				window.localStorage.setItem("keyEventDecrement", " Ctrl");
			}

			// Listen for requests from chrome.extension.sendRequest.

			chrome.extension.onRequest.addListener(

				function (request, sender, sendResponse) {

					switch (request.greeting) {

						// From:      popup.html
						// Request:   User clicks the Accept button on popup's form.
						// Action:    Set the form data into urli and request keys.js to add a keyListener.
						// Callback:  None.

						case "onPopupFormAccept":
							urli.setEnabled(request.enabled);
							urli.setTab(request.tab);
							urli.setSelection(request.selection);
							urli.setSelectionStart(request.selectionStart);
							urli.setIncrement(request.increment);
							urli.setZeros(request.zeros);
							if (localStorage["keyEnabled"] == 1) {
								chrome.tabs.sendRequest(request.tab.id, {greeting: "addKeyListener"}, function (response){});
								chrome.tabs.sendRequest(urli.getTab().id, {greeting: "updateKeys", keyCodeIncrement: localStorage["keyCodeIncrement"], keyEventIncrement: localStorage["keyEventIncrement"], keyCodeDecrement: localStorage["keyCodeDecrement"], keyEventDecrement: localStorage["keyEventDecrement"]}, function(response) {});
							}
							sendResponse({});
							break;

						// From:      options.html
						// Request:   User clicks the Save or Reset button on options's form.
						// Action:    Remove the keyListener and if keys are enabled, add it again and update new shortcut keys.
						// Callback:  None.

						case "onOptionsFormSave":
							if (urli.getEnabled()) {
								chrome.tabs.sendRequest(urli.getTab().id, {greeting: "removeKeyListener"}, function(response) {});
							}
							if (urli.getEnabled() && localStorage["keyEnabled"] == 1) {
								chrome.tabs.sendRequest(urli.getTab().id, {greeting: "addKeyListener"}, function (response){});
								chrome.tabs.sendRequest(urli.getTab().id, {greeting: "updateKeys", keyCodeIncrement: localStorage["keyCodeIncrement"], keyEventIncrement: localStorage["keyEventIncrement"], keyCodeDecrement: localStorage["keyCodeDecrement"], keyEventDecrement: localStorage["keyEventDecrement"]}, function(response) {});
							}
							sendResponse({});
							break;

						// From:      popup.html
						// Request:   Increment/Decrement/Clear buttons are pressed and they need to know if urli is enabled.
						// Action:    None (this is only a request to get urli).
						// Callback:  Respond with all of urli's properties.

						case "getUrli":
							sendResponse({enabled: urli.getEnabled(), tab: urli.getTab(), selection: urli.getSelection(), selectionStart: urli.getSelectionStart(), increment: urli.getIncrement(), zeros: urli.getZeros()});
							break;

						// From:      popup.html
						// Request:   Clear button is pressed and we need to clear urli's contents.
						// Action:    Disable everything by calling clear() on urli and removing all listeners.
						// Callback:  None.

						case "clearUrli":
							chrome.tabs.sendRequest(urli.getTab().id, {greeting: "removeKeyListener"}, function (response){});
							chrome.tabs.onUpdated.removeListener(onUpdatedTab);
							urli.clear();
							sendResponse({});
							break;

						// From:      popup.html, keys.js
						// Request:   Increment or decrement request from a button or shortcut key.
						// Action:    Modify the current tab's URL by incrementing it or decrementing it and update the tab with the new URL.
						// Callback:  None.

						case "modifyUrliAndUpdateTab":
							modifyURL(request.action);
							updateTab();
							if (localStorage["keyEnabled"] == 1) {
								chrome.tabs.onUpdated.addListener(onUpdatedTab);
							}
							sendResponse({});
							break;

						// Unspecified request -- should not be needed!

						default:
							sendResponse({});
							break;
					}
				}
			);

			// Modifies the selection to either increment or decrement (depending
			// on what the action is), and then updates the url in urli's tab
			// object.  Called by modifyUrliAndUpdateTab.

			function modifyURL(action) {

				var selectionString = urli.getSelection();
				var selectionInteger = parseInt(selectionString, 10); // Base 10 needed due to bug with parseInt for leading zeros
				var selectionStart = urli.getSelectionStart();
				var increment = parseInt(urli.getIncrement(), 10); // Increment is really being stored as a String for some reason (but why?)!
				var zeros = urli.getZeros();

				// The user somehow was able to submit the form without properly
				// selecting the selection from the URL textArea.

				if (selectionStart == -1) {
					return; // URL won't change.
				}

				// If there are leading zeros and the user wants to keep them
				// and if the selection isn't just "0" (which doesn't apply to
				// keeping the leading zero due to the single digit).

				if (selectionString.charAt(0) == '0' && zeros && selectionString != "0") {

					// Count how many leading zeros there are.

					var countZeros = 0;
					var selectionStringLength = selectionString.length;
					for (var i = 0; i < selectionStringLength; i++) {

						// If we encounter the first non-zero digit, stop counting
						// leading zeros.

						if (selectionString.charAt(i) != '0') {
							break;
						}
						else {
							countZeros++;
						}
					}

					// Just gets the length (without the zeros) before doing the increment/decrement.

					selectionStringLength = ("" + selectionInteger).length;

					if (action == "Increment") {

						// selectionInteger already strips the zeros, we only care about the value here.

						selectionString = "" + (selectionInteger + increment);
					}

					else if (action == "Decrement") {

						// selectionInteger already strips the zeros, we only care about the value here.

						selectionString = "" + (selectionInteger - increment >= 0 ? selectionInteger - increment : 0);	
					}

					// Now count how many digits there are after the increment.

					newSelectionStringLength = selectionString.length;

					// The difference in amount of digits is found by simply
					// subtracting the lengths of the new and original
					// selectionStrings.  E.g., original = "9" and new = "10"
					// would mean a difference of one digit.  Note there is no
					// no need to cast the absolute value in case of decrement.

					var differenceInAmountOfDigits = newSelectionStringLength - selectionStringLength;

					// To find out how many zeros to pad, just count how many
					// zeros there were to begin with.  Then subtract the
					// difference in amount of digits between the original and
					// new (as calculated above).  This is because if the new
					// takes up one or more digits compared to the original,
					// then we should remove one or more zeros accordingly.
					// E.g. original = "009" and new = "010" means we need to
					// remove one of the leading zeros and only pad one zero
					// instead of two.

					var length = countZeros - differenceInAmountOfDigits;
					var paddedZeros = "";
					for (var i = 0; i < length; i++) {
						paddedZeros += "0";
					}

					// Pad with zeros.

					selectionString = paddedZeros + selectionString;
				}

				// Either there are no leading zeros or the user wants them removed.
				// Therefore, just use selectionInteger instead of the string.

				else {

					if (action == "Increment") {

						selectionString = "" + (selectionInteger + increment);
					}

					else if (action == "Decrement") {

						// A check on the subtraction of pageValue needs to be done to ensure
						// that the user cannot decrement below 0 (design decision).

						selectionString = "" + (selectionInteger - increment >= 0 ? selectionInteger - increment : 0);
					}
				}

				// Update the tab object with the updated url and save it in urli.
				// Also save the "new" selectionString (which was just incremented
				// or decremented in this function).

				var tab = urli.getTab();
				var URL = tab.url;
				var firstPartURL = URL.substring(0, selectionStart);
				var secondPartURL = URL.substring(selectionStart + urli.getSelection().length);

				tab.url = firstPartURL + selectionString + secondPartURL;
				urli.setTab(tab);					// Update urli's tab.
				urli.setSelection(selectionString);	// Update urli's selection.
			}

			// After the url is modified in modifyurl, go ahead and update
			// the tab to the new url using the chrome API's chrome.tabs.update.

			function updateTab() {
				chrome.tabs.getSelected(null, function(tab) {
					if (tab.id != urli.getTab().id) {
						return;
					}
					chrome.tabs.update(tab.id, {url:urli.getTab().url});
				});
			}

			// Necessary for the keys.  When the tab changes the URL due to
			// increment or decrement, we must send another request to add
			// a keyListener to the new URL page.  This function is called by the
			// tab listener chrome.tabs.onUpdated.addListener(onUpdatedTab),
			// in modifyUrliAndUpdateTab.

			function onUpdatedTab(tabId, changeInfo, tab) {
				if (!urli.getEnabled()) { // Forces the listener to be removed on this tab.
					chrome.tabs.onUpdated.removeListener(arguments.callee);
					return;
				}
				if (tabId != urli.getTab().id) {
					return;
				}
				chrome.tabs.sendRequest(tabId, {greeting: "addKeyListener"}, function (response){});
				chrome.tabs.sendRequest(urli.getTab().id, {greeting: "updateKeys", keyCodeIncrement: localStorage["keyCodeIncrement"], keyEventIncrement: localStorage["keyEventIncrement"], keyCodeDecrement: localStorage["keyCodeDecrement"], keyEventDecrement: localStorage["keyEventDecrement"]}, function(response) {});
			}

		</script>

	</head>

</html>
